package time_task

import (
	. "chess_platform/internal/common"
	"chess_platform/models/pc"
	"fmt"
	"github.com/astaxie/beego/orm"
)

//每天凌晨执行，统计昨天的数据
//统计每天亲友圈消耗的房卡数及桌子数
func StatDayClub(r map[int64]int64) error {
	return ForExecute(listAllClub, RecordDayClub, r[RecordDayClub])
}

func listAllClub(t int64) error {
	var count int64 //先统计有多少个没有解散的亲友圈
	sqlCount := fmt.Sprintf(`
		SELECT
			COUNT(1)
		FROM
			%v
		WHERE
			status != %v
	`, TableClub, ClubDismiss)
	o := NewDBOrm(DBChess)
	o.Raw(sqlCount).QueryRow(&count)
	if count == 0 { //没有亲友圈，统计毛线
		LogPc.Info("暂时没有亲友圈可以统计")
		return nil
	}
	sqlClub := fmt.Sprintf(`
		SELECT
			c.id AS club_id,c.password,c.host_id,c.game_id,c.status,
			c.name AS club_name,u.nickname AS host_name
		FROM
			%v AS c
		LEFT JOIN
			%v AS u
		ON c.host_id = u.uid
		WHERE
			c.status != %v
		LIMIT ?,?
	`, TableClub, TableClientUser, ClubDismiss) //已经解散的亲友圈不要统计了
	//每次取10个,不足10个就有多少取多少

	var i, index, size int64
	size = 10
	for index = 1; i < count; index++ {
		var clubInfo []ClubInfo
		limit := (index - 1) * size
		n, err := o.Raw(sqlClub, limit, size).QueryRows(&clubInfo)
		if err != nil {
			return err
		}
		//n才是真实取了多少个
		i = limit + n
		err = statDayClub(t, clubInfo)
		if err != nil {
			return err
		}
	}
	return nil
}

type ClubInfo struct {
	ClubId   int64  `json:"club_id"`
	Password int64  `json:"password"`
	HostId   int64  `json:"host_id"`
	HostName string `json:"host_name"`
	GameId   int64  `json:"game_id"`
	TableNum int64  `json:"table_num"`
	ClubName string `json:"club_name"`
	Status   int64  `json:"status"`
}

func statDayClub(t int64, clubInfo []ClubInfo) error {
	LogPc.Info("-----------------进入统计亲友圈函数----------------------------")
	var (
		Member     int64 //亲友圈成员数量
		Table      int64 //亲友圈开房数量
		Card       int64 //亲友圈消耗房卡数量
		start, end = StartEndTimeByTimestamp(t)
		//tableName  = GetMonthTableByTimestamp(TableDayClub, t)
		tableName = TableDayClub
	)
	//亲友圈成员数
	sqlClubMember := fmt.Sprintf(`
			SELECT
				COUNT(1)
			FROM
				%v
			WHERE
				cid = ? AND status IN (%v,%v)
		`, TableClubMember, ClubMemberMute, ClubMemberNormal)
	//亲友圈开房数,包含了四种情况,0未结束1正常结束2过期结束3投票解散
	sqlClubTable := fmt.Sprintf(`
			SELECT
				COUNT(1)
			FROM
				%v
			WHERE
				clubid = ? AND createtime > %v AND createtime < %v
		`, TableRoom, start, end)
	//亲友圈消耗房卡数
	sqlClubCard := fmt.Sprintf(`
			SELECT
				IF(SUM(fee) is NULL,0,SUM(fee)) AS card
			FROM
				%v
			WHERE
				clubid = ? AND createtime > %v AND createtime < %v
		`, TableRoom, start, end)
	o := NewDBOrm(DBChess)
	og := NewDBOrm(DBChessSysData)
	//一条一条的数据查找统计写入
	for _, v := range clubInfo {
		//统计亲友圈每天消耗的房卡及开房数,成员数
		err := o.Raw(sqlClubMember, v.ClubId).QueryRow(&Member)
		if err != nil {
			LogPc.Error("统计亲友圈成员数量失败:", err.Error())
		}
		err = o.Raw(sqlClubTable, v.ClubId).QueryRow(&Table)
		if err != nil {
			LogPc.Error("统计亲友圈当天开房数量失败:", err.Error())
		}
		err = o.Raw(sqlClubCard, v.ClubId).QueryRow(&Card)
		if err != nil {
			LogPc.Error("统计亲友圈当天消耗房卡数量失败:", err.Error())
		}
		//把每天统计的数据加到总数表里
		pc.UpdateClubCardTable(Member, v.ClubId)
		data := map[string]interface{}{
			"create_time": end - 1, //当日的23:59:59
			"club_id":     v.ClubId,
			"password":    v.Password,
			"club_name":   v.ClubName,
			"host_id":     v.HostId,
			"host_name":   v.HostName,
			"game_id":     v.GameId,
			"game_name":   GameNameByGameId(v.GameId, og),
			"status":      v.Status,
			"member":      Member,
			"table":       Table,
			"card":        Card,
		}
		pc.NewClubStat(data, tableName)
	}

	LogPc.Info("-----------------退出统计亲友圈函数----------------------------")
	return nil
}

//获取游戏名字
func GameNameByGameId(gameId int64, multiOrm ...orm.Ormer) string {
	if gameId == 0 {
		return ""
	}
	Key := fmt.Sprintf("GameName-%v", gameId)
	var gameName string
	if MemCache.IsExist(Key) {
		gameName = MemCache.Get(Key).(string)
	}
	if gameName == "" {
		sql := fmt.Sprintf(`
		SELECT
			name
		FROM
			%v
		WHERE
			game_id = %v
	`, TableGameList, gameId)
		o := NewOrm(multiOrm, DBChessSysData)
		err := o.Raw(sql).QueryRow(&gameName)
		if CheckNoExist(err) {
			return ""
		}
		MemCache.Put(Key, gameName, 6000) //10分钟
	}
	return gameName
}
func PutClubToRedisCache() error {
	return listClub()
}

func listClub() error {
	var count int64 //先统计有多少个没有解散的亲友圈
	sqlCount := fmt.Sprintf(`
		SELECT
			COUNT(1)
		FROM
			%v
		WHERE
			status != %v
	`, TableClub, ClubDismiss)
	o := NewDBOrm(DBChess)
	o.Raw(sqlCount).QueryRow(&count)
	if count == 0 { //没有亲友圈，统计毛线
		LogPc.Info("暂时没有亲友圈可以统计")
		return nil
	}
	//亲友圈信息
	sqlClub := fmt.Sprintf(`
		SELECT
			id AS club_id,host_id,password,table_num,game_id
		FROM
			%v
		WHERE
			status != %v
		LIMIT ?,?
		`, TableClub, ClubDismiss)
	//每次取10个,不足10个就有多少取多少

	var i, index, size int64
	size = 10
	for index = 1; i < count; index++ {
		var clubInfo []ClubInfo
		limit := (index - 1) * size
		n, err := o.Raw(sqlClub, limit, size).QueryRows(&clubInfo)
		if err != nil {
			return err
		}
		//n才是真实取了多少个
		i = limit + n
		err = putClubToRedisCache(clubInfo)
		if err != nil {
			return err
		}
	}
	return nil
}

//每天凌晨把亲友圈成员信息全部刷新到redis里
func putClubToRedisCache(clubInfo []ClubInfo) error {
	//只有正常或禁言的成员才是属于亲友圈成员
	sqlClubMember := fmt.Sprintf(`
		SELECT
			uid
		FROM
			%v
		WHERE
			status IN (%v,%v) AND cid = ?
	`, TableClubMember, ClubMemberNormal, ClubMemberMute)
	o := orm.NewOrm()
	o.Using(DBChess)
	//一条一条的数据查找统计写入
	for _, v := range clubInfo {

		Key := fmt.Sprintf("%v%v", KeyClub, v.ClubId)
		Redis.HSet(Key, "host", v.HostId)
		Redis.HSet(Key, "password", v.Password)
		Redis.HSet(Key, "table_num", v.TableNum)
		gameType, playType := AnalysisGameId(v.GameId)
		Redis.HSet(Key, "game_type", gameType)
		Redis.HSet(Key, "play_type", playType)

		//获取亲友圈成员id
		var MemberId []int64
		_, err := o.Raw(sqlClubMember, v.ClubId).QueryRows(&MemberId)
		if err != nil {
			LogPc.Error(fmt.Sprintf("查找俱乐部(ID:%v,Password:%v)成员时失败:%v", err, v.ClubId, v.Password))
			continue
		}
		for _, v := range MemberId {
			Redis.HSet(Key, v, v)
		}
	}
	return nil
}

//每天晚上11:40开始前把亲友圈的day_table,day_card置为0
func ClearClubData() error {
	sql := fmt.Sprintf("UPDATE %v SET day_card = 0,day_table = 0", TableClub)
	o := NewDBOrm(DBChess)
	o.Raw(sql).Exec()
	return nil
}
